package jpave.manager;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.event.CaretListener;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.Vector;


import util.methods.BlastArgs;
import util.Debug.ErrorReport;
import util.ui.ButtonComboBox;
import util.ui.UserPrompt;

public class EditAnnoPanel extends JPanel {
	private static final long serialVersionUID = 4830755874697242929L;
	
	private static final int COLUMN_WIDTH = 200;
	private static final int TAB_WIDTH = 20;
	private static final int COL_MINUS_TAB = COLUMN_WIDTH-TAB_WIDTH;
	private static final int FIELD_WIDTH_SHORT = 15;
	private static final int FIELD_WIDTH = 30;
	public static final String SEARCH_PGM_DEFAULT = "TCW Select";
	/****************************************************
	 * annotation panel for adding a new annoDB
	 */
	public EditAnnoPanel(ManagerFrame parentFrame) {
		theParentFrame = parentFrame;
	
		lblTaxonomy = new JLabel("Taxonomy");
		txtTaxonomy = new JTextField(FIELD_WIDTH_SHORT);
		
		btnGenHitFile = new JRadioButton("Generate Hit Tabular File");
		btnGenHitFile.setBackground(ManagerFrame.BGCOLOR);
		btnGenHitFile.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				lblDBfasta.setEnabled(true);
				txtDBfasta.setEnabled(true);
				lblParams.setEnabled(true);
				txtParams.setEnabled(true);
				lblSearchPgms.setEnabled(true);
				cmbSearchPgms.setSelectedItem(SEARCH_PGM_DEFAULT);
				
				lblUseDBfasta.setEnabled(false);
				txtUseDBfasta.setEnabled(false);
				lblTabularFile.setEnabled(false);
				txtTabularFile.setEnabled(false);
				txtTabularFile.setText("");
			}
		});
		
		lblDBfasta = new JLabel("annoDB FASTA file");
		txtDBfasta = new FileTextField(theParentFrame, FIELD_WIDTH, true);
		
		btnUseExistingHitFile = new JRadioButton("Use Existing Hit Tabular File");
		btnUseExistingHitFile.setBackground(ManagerFrame.BGCOLOR);
		btnUseExistingHitFile.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				lblDBfasta.setEnabled(false);
				txtDBfasta.setEnabled(false);
				lblParams.setEnabled(false);
				txtParams.setEnabled(false);
				lblSearchPgms.setEnabled(false);
				cmbSearchPgms.setEnabled(false);
				
				lblUseDBfasta.setEnabled(true);
				txtUseDBfasta.setEnabled(true);
				lblTabularFile.setEnabled(true);
				txtTabularFile.setEnabled(true);
			}
		});
		
		lblTabularFile = new JLabel("Hit Tabular File");
		txtTabularFile = new FileTextField(theParentFrame, FIELD_WIDTH, false);
		
		lblParams = new JLabel("Parameters");
		txtParams = new JTextField(FIELD_WIDTH);
		
		// XXX add 
		lblSearchPgms = new JLabel("Search program ");
		cmbSearchPgms = new ButtonComboBox();
		cmbSearchPgms.setBackground(ManagerFrame.BGCOLOR);
		Vector <String> pgm = BlastArgs.getSearchPgms();
		if (pgm.size()==1) {
			cmbSearchPgms.addItem(pgm.get(0));
			cmbSearchPgms.setSelectedIndex(0);
		}
		else {
			for (String p: pgm) cmbSearchPgms.addItem(p);
			cmbSearchPgms.setSelectedIndex(0); // TCW_Select
		}
		cmbSearchPgms.setMaximumSize(cmbSearchPgms.getPreferredSize());
		cmbSearchPgms.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setParamDefaults();
			}
		});
		
		lblUseDBfasta = new JLabel("annoDB FASTA file");
		txtUseDBfasta = new FileTextField(theParentFrame, FIELD_WIDTH, true);
		
		lblUnannotated = new JLabel("Unannotated only");
		chkUnannotated = new JCheckBox("");
		chkUnannotated.setBackground(ManagerFrame.BGCOLOR);
		
		lblDate = new JLabel("Date of annoDB download");
		txtDate = new JTextField(FIELD_WIDTH_SHORT);
		
		btnKeep = new JButton("Keep");
		btnKeep.setBackground(ManagerFrame.BGCOLOR);
		btnKeep.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (!dataIsValid()) return;
				theParentFrame.updateAnnoDBUI();
				if(isLoaded())
					theParentFrame.updateAnnoDBTaxonomy();
				
				setVisible(false);
				theParentFrame.setMainPanelVisible(true);
				
				theParentFrame.updateUI();
				theParentFrame.saveProject();
				theParentFrame.setFrameMode(ManagerFrame.FRAME_MODE_MAIN);
			}
		});
		
		btnDiscard = new JButton("Discard");
		btnDiscard.setBackground(ManagerFrame.BGCOLOR);
		btnDiscard.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if(theParentFrame.isRemoveAnnoOnDiscard()) {
					theParentFrame.clearCurrentAnnoDB();
					theParentFrame.updateUI();
				}
				
				setVisible(false);
				theParentFrame.setMainPanelVisible(true);
				theParentFrame.setFrameMode(ManagerFrame.FRAME_MODE_MAIN);
			}
		});
		
		btnReset = new JButton("Reset to Defaults");
		btnReset.setBackground(ManagerFrame.BGCOLOR);
		btnReset.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setTaxonomy("");
				setTabularFile("");
				cmbSearchPgms.setSelectedItem(SEARCH_PGM_DEFAULT);
				setDBfastaFile("");
				setParams("");
				setUnannotated(false);
				setDate("");
			}
		});
		
		btnHelp = new JButton("Help");
		btnHelp.setBackground(ManagerFrame.HELPCOLOR);
		btnHelp.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				UserPrompt.displayHTMLResourceHelp(theParentFrame, "AnnoDB Help", 
						"html/runSingleTCW/EditAnnoDBPanel.html");
			}
		});

		/** Edit Panel layout **/
		pnlMain = ManagerFrame.getPanel(false);
		
		ButtonGroup group = new ButtonGroup();
		group.add(btnGenHitFile);
		group.add(btnUseExistingHitFile);
		
		btnGenHitFile.setSelected(true);
		
		JPanel row = ManagerFrame.getPanel(true);
		row.add(lblTaxonomy);
		if(lblTaxonomy.getPreferredSize().width < COLUMN_WIDTH)
			row.add(Box.createHorizontalStrut(COLUMN_WIDTH - lblTaxonomy.getPreferredSize().width));
		row.add(txtTaxonomy);
		pnlMain.add(row);
		pnlMain.add(Box.createVerticalStrut(5));
		
		row = ManagerFrame.getPanel(true);
		row.add(btnGenHitFile);
		pnlMain.add(row);
		pnlMain.add(Box.createVerticalStrut(5));
		
		row = ManagerFrame.getPanel(true);
		row.add(Box.createHorizontalStrut(TAB_WIDTH));
		row.add(lblDBfasta);
		if(lblDBfasta.getPreferredSize().width < COL_MINUS_TAB)
			row.add(Box.createHorizontalStrut(COL_MINUS_TAB - lblDBfasta.getPreferredSize().width));
		row.add(txtDBfasta);
		pnlMain.add(row);
		pnlMain.add(Box.createVerticalStrut(5));
		
		row = ManagerFrame.getPanel(true);
		row.add(Box.createHorizontalStrut(TAB_WIDTH));
		row.add(lblSearchPgms);
		if(lblSearchPgms.getPreferredSize().width < COL_MINUS_TAB)
			row.add(Box.createHorizontalStrut(COL_MINUS_TAB - lblSearchPgms.getPreferredSize().width));
		row.add(cmbSearchPgms);
		pnlMain.add(row);
		pnlMain.add(Box.createVerticalStrut(5));

		row = ManagerFrame.getPanel(true);
		row.add(Box.createHorizontalStrut(TAB_WIDTH));
		row.add(lblParams);
		if(lblParams.getPreferredSize().width < COL_MINUS_TAB)
			row.add(Box.createHorizontalStrut(COL_MINUS_TAB - lblParams.getPreferredSize().width));
		row.add(txtParams);
		pnlMain.add(row);
		pnlMain.add(Box.createVerticalStrut(5));

		row = ManagerFrame.getPanel(true);
		row.add(btnUseExistingHitFile);
		pnlMain.add(row);
		pnlMain.add(Box.createVerticalStrut(5));

		row = ManagerFrame.getPanel(true);
		row.add(Box.createHorizontalStrut(TAB_WIDTH));
		row.add(lblTabularFile);
		if(lblTabularFile.getPreferredSize().width < COL_MINUS_TAB)
			row.add(Box.createHorizontalStrut(COL_MINUS_TAB - lblTabularFile.getPreferredSize().width));
		row.add(txtTabularFile);
		pnlMain.add(row);
		pnlMain.add(Box.createVerticalStrut(5));

		row = ManagerFrame.getPanel(true);
		row.add(Box.createHorizontalStrut(TAB_WIDTH));
		row.add(lblUseDBfasta);
		if(lblUseDBfasta.getPreferredSize().width < COL_MINUS_TAB)
			row.add(Box.createHorizontalStrut(COL_MINUS_TAB - lblUseDBfasta.getPreferredSize().width));
		row.add(txtUseDBfasta);
		pnlMain.add(row);
		pnlMain.add(Box.createVerticalStrut(10));

		row = ManagerFrame.getPanel(true);
		row.add(lblUnannotated);
		if(lblUnannotated.getPreferredSize().width < COLUMN_WIDTH)
			row.add(Box.createHorizontalStrut(COLUMN_WIDTH - lblUnannotated.getPreferredSize().width));
		row.add(chkUnannotated);
		pnlMain.add(row);
		pnlMain.add(Box.createVerticalStrut(5));

		row = ManagerFrame.getPanel(true);
		row.add(lblDate);
		if(lblDate.getPreferredSize().width < COLUMN_WIDTH)
			row.add(Box.createHorizontalStrut(COLUMN_WIDTH - lblDate.getPreferredSize().width));
		row.add(txtDate);
		pnlMain.add(row);
		pnlMain.add(Box.createVerticalStrut(15));
		
		row = ManagerFrame.getPanel(true);
		
		JPanel buttonPanel = ManagerFrame.getPanel(true);
		buttonPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
		
		buttonPanel.add(btnReset);
		buttonPanel.add(Box.createHorizontalStrut(10));
		buttonPanel.add(btnKeep);
		buttonPanel.add(Box.createHorizontalStrut(10));
		buttonPanel.add(btnDiscard);
		buttonPanel.add(Box.createHorizontalStrut(10));
		buttonPanel.add(btnHelp);
		
		row.add(Box.createHorizontalGlue());
		row.add(buttonPanel);
		row.add(Box.createHorizontalGlue());
		
		pnlMain.add(row);
		pnlMain.add(Box.createVerticalStrut(10));
		pnlMain.add(new JLabel("Hit tabular file = from any search program that produces a Blast-like tabular file"));
		pnlMain.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
		
		setBackground(ManagerFrame.BGCOLOR);
		add(pnlMain);

		lblUseDBfasta.setEnabled(false);
		txtUseDBfasta.setEnabled(false);
		lblTabularFile.setEnabled(false);
		txtTabularFile.setEnabled(false);
		
		setVisible(false);
	}
	private boolean dataIsValid()
	{
		String [] msg = new String [1];
		boolean valid = true;
		String tax = txtTaxonomy.getText().trim();
		if (tax.equals(""))
		{
			msg[0] = "Enter taxonomy string (label for this AnnoDB)";
			UserPrompt.displayInfo("Missing information", msg, true);
			valid = false;
			System.err.println("Please enter the taxonomy string (label for this AnnoDB)");
		}
		else {
			Pattern p = Pattern.compile("\\W");
			Matcher n = p.matcher(tax);
			if (n.find()) {
				msg[0] = "Taxonomy string " + tax + " must be letters, characters or '_' (underscore)";
				UserPrompt.displayInfo("Missing information", msg, true);
				valid = false;
				System.err.println(msg[0]);
			}
		}
		if (btnUseExistingHitFile.isSelected() && btnUseExistingHitFile.isEnabled()) // CAS 5/10/15
		{
			if (txtUseDBfasta.getText().trim().equals(""))
			{
				msg[0] = "Enter annoDB FASTA file";
				UserPrompt.displayInfo("Missing information", msg, true);
				System.err.println("Please enter the fasta file for the AnnoDB");
				valid = false;
			}
			if (txtTabularFile.getText().trim().equals(""))
			{
				msg[0] = "Enter hit tabular file";
				UserPrompt.displayInfo("Missing information", msg, true);
				System.err.println("Please enter the hit tabular file");
				valid = false;
			}
		}
		else if (btnGenHitFile.isSelected() && btnGenHitFile.isEnabled())
		{
			if (txtDBfasta.getText().trim().equals(""))
			{
				msg[0] = "Enter annoDB FASTA file";
				UserPrompt.displayInfo("Missing information", msg, true);
				System.err.println("Please enter the fasta file for the AnnoDB");
				valid = false;
			}
			
		}
		return valid;
	}
	public void setTaxonomy(String taxonomy) { txtTaxonomy.setText(taxonomy); }
	public String getTaxonomy() { return txtTaxonomy.getText(); }
	
	public void setDBfastaFile(String file) {
			txtUseDBfasta.setText(file);
			txtDBfasta.setText(file);
	}
	public String getDBfastaFile() {
		if(btnGenHitFile.isSelected())
			return txtDBfasta.getText();
		return txtUseDBfasta.getText();
	}
	
	public void setParams(String params) { 
		if (!params.equals("")) txtParams.setText(params); 
		else setParamDefaults();
	}
	private void setParamDefaults () {
		String selected = cmbSearchPgms.getSelectedItem();
		if (selected.equals("blast")) txtParams.setText(BlastArgs.getBlastxOpDefaults());
		else if (selected.equals("diamond")) txtParams.setText(BlastArgs.getDiamondOpDefaults());
		else if (selected.equals("usearch")) txtParams.setText(BlastArgs.getUsearchOpDefaults());
		else txtParams.setText("");
	}
	public String getParams() { return txtParams.getText(); }
	
	public void setTabularFile(String file) { 
		txtTabularFile.setText(file); 
		if (!file.equals("")) {
			btnGenHitFile.setSelected(false); // CAS 2/16/15
			btnUseExistingHitFile.setSelected(true);
		}
	}
	public String getTabularFile() { return txtTabularFile.getText(); }
	
	public void setUnannotated(boolean unannotated) { chkUnannotated.setSelected(unannotated); }
	public boolean getUnannotated() { return chkUnannotated.isSelected(); }
	
	public void setDate(String date) { txtDate.setText(date); }
	public String getDate() { return txtDate.getText(); }
	
	public void setSearchPgm(String pgm) {
		boolean set = cmbSearchPgms.setSelectedItem(pgm);
		if (!set) {
			if (!pgm.equals(SEARCH_PGM_DEFAULT)) System.err.println("Search program " + pgm + " not available");
			cmbSearchPgms.setSelectedIndex(0);
		}
	}
	public String getSearchPgm() {return cmbSearchPgms.getSelectedItem();}

	public void setLoaded(boolean loaded) { 
		bIsLoaded = loaded; 
		
		btnGenHitFile.setEnabled(!bIsLoaded);
		btnUseExistingHitFile.setEnabled(!bIsLoaded);
		lblDBfasta.setEnabled(!bIsLoaded);
		txtDBfasta.setEnabled(!bIsLoaded);
		lblParams.setEnabled(!bIsLoaded);
		txtParams.setEnabled(!bIsLoaded);
		lblTabularFile.setEnabled(!bIsLoaded);
		txtTabularFile.setEnabled(!bIsLoaded);
		lblUseDBfasta.setEnabled(!bIsLoaded);
		txtUseDBfasta.setEnabled(!bIsLoaded);
		lblUnannotated.setEnabled(!bIsLoaded);
		chkUnannotated.setEnabled(!bIsLoaded);
		lblDate.setEnabled(!bIsLoaded);
		txtDate.setEnabled(!bIsLoaded);
		btnReset.setEnabled(!bIsLoaded);
		lblSearchPgms.setEnabled(!bIsLoaded);
		cmbSearchPgms.setEnabled(!bIsLoaded);
	}
	public boolean isLoaded() { return bIsLoaded; }
	
	/****************************************************
	 * EditAnnoPanel private variables
	 */
	private ManagerFrame theParentFrame = null;
	private JPanel pnlMain = null;
	
	private JLabel lblTaxonomy = null;
	private JTextField txtTaxonomy = null;
	
	private JLabel lblSearchPgms=null;
	private ButtonComboBox cmbSearchPgms = null;
	private JRadioButton btnGenHitFile = null;
	private JRadioButton btnUseExistingHitFile = null;
	
	private JLabel lblDBfasta = null;
	private FileTextField txtDBfasta = null;
	
	private JLabel lblParams = null;
	private JTextField txtParams = null;
	
	private JLabel lblTabularFile = null;
	private FileTextField txtTabularFile = null;
	
	private JLabel lblUseDBfasta = null;
	private FileTextField txtUseDBfasta = null;
	
	private JLabel lblUnannotated = null;
	private JCheckBox chkUnannotated = null;
	
	private JLabel lblDate = null;
	private JTextField txtDate = null;
	
	private JButton btnReset = null, btnKeep = null, btnDiscard = null, btnHelp = null;
	
	private boolean bIsLoaded = false;
	
	private File curAnnoDir = null;
	
	/*****************************************************************
	 * Class for reading files
	 */
	public class FileTextField extends JPanel {
		private static final long serialVersionUID = 6670096855895700182L;
		
		public FileTextField(ManagerFrame parentFrame, int size, final boolean annodb) {
			theParentFrame = parentFrame;
			setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
			setAlignmentX(Component.LEFT_ALIGNMENT);
			setBackground(ManagerFrame.BGCOLOR);
			
			txtValue = new JTextField(size);
			Dimension dTxt = txtValue.getPreferredSize(); 
			txtValue.setMaximumSize(dTxt);
			txtValue.setMinimumSize(dTxt);
			
			btnFindFile = new JButton("...");
			btnFindFile.setBackground(ManagerFrame.BGCOLOR);
			Dimension dBtn = new Dimension();
			dBtn.width = btnFindFile.getPreferredSize().width;
			dBtn.height = dTxt.height;
			
			btnFindFile.setMaximumSize(dBtn);
			btnFindFile.setMinimumSize(dBtn);
			btnFindFile.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent arg0) {
					try {
						JFileChooser fc = new JFileChooser();
						if (curAnnoDir==null) 
							curAnnoDir = theParentFrame.getAnnoDBPath();
						if (annodb)  fc.setCurrentDirectory(curAnnoDir);
						else fc.setCurrentDirectory(theParentFrame.getProjPath());
						
						if(fc.showOpenDialog(theParentFrame) == JFileChooser.APPROVE_OPTION) {
								String path = fc.getSelectedFile().getAbsolutePath();
								if (annodb) curAnnoDir =  new File (path); /// CAS 7/1/13
								int index = path.indexOf(theParentFrame.getLibPath().getAbsolutePath());
								if(index >= 0) {
									txtValue.setText(path.substring(index + theParentFrame.getLibPath().getAbsolutePath().length() + 1));
								}
								else
									txtValue.setText(fc.getSelectedFile().getAbsolutePath());
						}
					}
					catch(Exception e) {
						ErrorReport.prtReport(e, "Error finding file");
					}
					
				}});
			
			add(txtValue);
			add(btnFindFile);
		}
		
		public void addCaretListener(CaretListener l) { txtValue.addCaretListener(l); }
		public void addActionListener(ActionListener l) { btnFindFile.addActionListener(l); }
		
		public void setText(String text) { txtValue.setText(text); }
		public String getText() { return txtValue.getText(); }
		
		public void setEnabled(boolean enabled) {
			txtValue.setEnabled(enabled);
			btnFindFile.setEnabled(enabled);
		}
		
		private ManagerFrame theParentFrame = null;
		
		private JTextField txtValue = null;
		private JButton btnFindFile = null;
	}
}
